package com.htd.base.common.config.interceptor;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.htd.base.common.annotation.Translate;
import com.htd.base.common.annotation.TranslateFromField;
import com.htd.base.common.config.LsCoreProperties;
import com.htd.base.common.util.BaseDateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Signature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Intercepts({
        @Signature(
                type = StatementHandler.class,
                method = "prepare",
                args = {Connection.class, Integer.class}
        )
})
@Component
public class TranslateInsertInterceptor implements InnerInterceptor {

    @Autowired
    private LsCoreProperties lsCoreProperties;

    @Autowired
    private DynamicRoutingDataSource dynamicRoutingDataSource;

    @Override
    public void beforePrepare(StatementHandler sh, Connection connection, Integer i) {
        // 检查是否是insert语句
        String sql = sh.getBoundSql().getSql();
        if (sql.toLowerCase().startsWith("insert") || sql.toLowerCase().startsWith("update")) {
            // 获取参数对象
            Object parameterObj = sh.getParameterHandler().getParameterObject();
            if (sql.toLowerCase().startsWith("update")) {
                if (sh.getParameterHandler().getParameterObject() instanceof Map) {
                    HashMap<String, Object> map = (HashMap<String, Object>) parameterObj;
                    parameterObj = map.get("param1");
                } else {
                    log.warn("[Trans. plugin] ATP-TranslateInsertInterceptor-Intercept update operation, unsupported parameter types, Automatic update of business ID failed");
                }
            }
            boolean translate = false;
            if (parameterObj != null) {
                // 获取对象的类
                Class<?> clazz = parameterObj.getClass();
                // 获取类上面的注解
                Annotation[] annotations = clazz.getAnnotations();
                for (Annotation annotation : annotations) {
                    if (annotation instanceof Translate) {
                        translate = true;
                        break;
                    }
                }
                // 如果没有注解，则不翻译
                if (!translate) {
                    return;
                }
                String tableId = null;
                Set<String> itemKeys = new HashSet<>();
                Class<?> currentClass = parameterObj.getClass();
                Field[] fields = currentClass.getDeclaredFields();
                // 遍历对象的所有字段
                for (Field field : fields) {
                    if (field.isAnnotationPresent(TableId.class)) {
                        // 反射设置字段值为 null 或者其他默认值
                        field.setAccessible(true);
                        // 找到需要翻译的字段
                        try {
                            tableId = field.get(parameterObj).toString();
                        } catch (IllegalAccessException e) {
                            log.error("[Trans. plugin] ATP-TranslateInsertInterceptor-TableId IllegalAccessException", e);
                        }
                    } else if (field.isAnnotationPresent(TranslateFromField.class)) {
                        // 反射设置字段值为 null 或者其他默认值
                        field.setAccessible(true);
                        // 找到所有的 itemkey的值
                        try {
                            if (field.get(parameterObj) != null) {
                                itemKeys.add("'" + field.get(parameterObj).toString() + "'");
                            }
                        } catch (IllegalAccessException e) {
                            log.error("[Trans. plugin] ATP-TranslateInsertInterceptor-TranslateFromField IllegalAccessException", e);
                        }
                    }
                }
                if (!itemKeys.isEmpty()) {
                    // 保存当前数据源
                    String currentDataSource = DynamicDataSourceContextHolder.peek();
                    Connection languageConnection = null;
                    try {
                        // 切换到语言数据源
                        String languageDataSource = lsCoreProperties.getBase().language().database().getKey();
                        DynamicDataSourceContextHolder.push(languageDataSource);
                        log.debug("[Trans. plugin] Switched to language datasource: {}", languageDataSource);

                        // 获取新的连接
                        DataSource dataSource = dynamicRoutingDataSource.getDataSource(languageDataSource);
                        try {
                            languageConnection = dataSource.getConnection();
                        } catch (SQLException e) {
                            throw new RuntimeException(e);
                        }
                        log.debug("[Trans. plugin] Got new connection for language datasource");

                        StringBuffer updateSql = new StringBuffer();
                        String dbType = "mariadb"; // 默认使用 MariaDB
                        try {
                            dbType = getDbType(languageConnection);
                        } catch (SQLException e) {
                            log.error("[Trans. plugin] 獲取數據庫類型失敗，使用默認類型 MariaDB", e);
                        }

                        if ("postgresql".equals(dbType)) {
                            // PostgreSQL 需要 schema 和字段引号
                            updateSql.append(" UPDATE \"public\".\"auto_language_item\" SET ");
                            updateSql.append(" \"from_data_id\" = '").append(tableId).append("', ");
                            updateSql.append(" \"update_user_id\" = 'Interceptor', ");
                            updateSql.append(" \"update_time\" = '").append(BaseDateUtils.parseLocalDateTime2String(LocalDateTime.now())).append("'");
                            updateSql.append(" WHERE \"item_key\" in (").append(String.join(",", itemKeys)).append(")");
                            updateSql.append(" AND \"deleted\" = '1'");
                            updateSql.append(" AND \"from_data_id\" is null;");
                        } else {
                            // MariaDB/MySQL 不需要引号
                            updateSql.append(" UPDATE auto_language_item SET ");
                            updateSql.append(" from_data_id = '").append(tableId).append("', ");
                            updateSql.append(" update_user_id = 'Interceptor', ");
                            updateSql.append(" update_time = '").append(BaseDateUtils.parseLocalDateTime2String(LocalDateTime.now())).append("'");
                            updateSql.append(" WHERE item_key in (").append(String.join(",", itemKeys)).append(")");
                            updateSql.append(" AND deleted = '1'");
                            updateSql.append(" AND from_data_id is null;");
                        }

                        try (java.sql.Statement stmt = languageConnection.createStatement()) {
                            stmt.execute(updateSql.toString());
                            log.debug("[Trans. plugin] ATP-TranslateInsertInterceptor-updateStatement: {} success", updateSql);
                        } catch (Exception e) {
                            log.error("[Trans. plugin] ATP-TranslateInsertInterceptor-updateStatement: " + updateSql, e);
                        }
                    }catch (Exception e) {
                        log.error("[Trans. plugin] ATP-TranslateInsertInterceptor-updateStatement error", e);
                    } finally {
                        // 关闭语言数据源连接
                        if (languageConnection != null) {
                            try {
                                languageConnection.close();
                            } catch (SQLException e) {
                                log.error("[Trans. plugin] Failed to close language connection", e);
                            }
                        }
                        // 恢复原始数据源
                        if (currentDataSource != null) {
                            DynamicDataSourceContextHolder.push(currentDataSource);
                            log.debug("[Trans. plugin] Restored original datasource: {}", currentDataSource);
                        }
                    }
                }
            }
        }
    }

    @Override
    public void setProperties(Properties properties) {
        // 设置属性
    }

    private String getDbType(Connection connection) throws SQLException {
        String url = connection.getMetaData().getURL().toLowerCase();
        if (url.contains("postgresql")) {
            return "postgresql";
        } else if (url.contains("mariadb") || url.contains("mysql")) {
            return "mariadb";
        }
        return "mariadb"; // 默认返回 MariaDB
    }
}
